﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
namespace HB.Base
{
    /// <summary>
    /// 本地redis功能,针对数值型，具备过期自动删除功能
    /// </summary>
    public class LocalRedis<T> where T : struct
    {
        ConcurrentDictionary<string, RedisValue> redis = new ConcurrentDictionary<string, RedisValue>();
        class RedisValue
        {
            internal DateTime OutTime { get; set; }
            public T Value { get; set; }
        }
        /// <summary>
        /// 设置含有过期时间的数据
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="lifeTime"></param>
        public void Set(string key, T value, TimeSpan lifeTime)
        {
            redis[key] = new RedisValue() { OutTime = DateTime.Now.Add(lifeTime), Value = value };
        }
        /// <summary>
        /// 设置永久有效的数据
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void Set(string key, T value)
        {
            redis[key] = new RedisValue() { OutTime = DateTime.MaxValue, Value = value };
        }
        /// <summary>
        /// 是否存在非过期数据
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Exists(string key)
        {
            if (redis.TryGetValue(key, out var v))
            {
                if (v.OutTime < DateTime.Now)
                {
                    redis.TryRemove(key, out RedisValue v2);
                    return false;
                }
                else { return true; }
            }
            return false;
        }
        /// <summary>
        /// 获取指定key的非过期数据
        /// </summary>
        /// <param name="key"></param>
        /// <param name="failDefaultValue">过期或不存时的默认值</param>
        /// <returns></returns>
        public T Get(string key, T failDefaultValue = default(T))
        {
            if (Exists(key))
            {
                if (redis.TryGetValue(key, out var value))
                {
                    return value.Value;
                }
            }
            return failDefaultValue;

        }
        /// <summary>
        /// 获取所有非过期key
        /// </summary>
        /// <returns></returns>
        public string[] GetKeys()
        {
            var keys = redis.Keys.ToArray();
            List<string> ls = new List<string>(keys.Length);
            foreach (var key in keys)
            {
                if (Exists(key)) { ls.Add(key); }
            }
            return ls.ToArray();
        }
        /// <summary>
        /// 获取所有指定key的数据
        /// </summary>
        /// <param name="keys"></param>
        /// <param name="failDefaultValue"></param>
        /// <returns></returns>
        public T[] GetValues(string[] keys, T failDefaultValue = default(T))
        {
            T[] values = new T[keys.Length];
            for (int i = 0; i < keys.Length; i++)
            {
                values[i] = Get(keys[i], failDefaultValue);
            }
            return values;
        }
        /// <summary>
        /// 清理指定的key
        /// </summary>
        /// <param name="key"></param>
        public void Remote(string key)
        {
            redis.TryRemove(key, out var v);
        }
        /// <summary>
        /// 清理所有数据
        /// </summary>
        public void Clear()
        {
            redis.Clear();
        }
    }
}
